package com.wecommodule.bpm.ext.framework.config.support;

import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import okhttp3.OkHttpClient;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.http.MediaType;
import org.springframework.http.client.OkHttp3ClientHttpRequestFactory;
import org.springframework.http.converter.AbstractHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.client.RestTemplate;

import java.util.ArrayList;
import java.util.List;

/**
 * RestTemplate configuration.
 * Note it only supports RESTful APIs.
 *
 */
@SuppressWarnings("ClassWithoutConstructor")
public class RestTemplateConfigSupport {

    /**
     * 生成一个RestTemplate
     *
     * @param okHttpClient             OkHttpClient客户端
     * @param properties               HTTP 配置
     * @param additionalJSONMediaTypes 所需要支持的媒体类型
     * @return a RestTemplate.
     */
    @SuppressWarnings("FeatureEnvy")
    @NotNull
    public RestTemplate buildRestTemplate(@NotNull OkHttpClient okHttpClient, @NotNull HttpConfigProperties properties,
                                          @Nullable MediaType[] additionalJSONMediaTypes) {
        RestTemplateBuilder builder = new RestTemplateBuilder().requestFactory(
                () -> new OkHttp3ClientHttpRequestFactory(okHttpClient));
        if (properties.getRootUri() != null) {
            builder = builder.rootUri(properties.getRootUri());
        }
        if (properties.hasPrincipal()) {
            builder = builder.basicAuthentication(properties.getUsername(), properties.getPassword());
        }
        List<HttpMessageConverter<?>> converters = buildMessageConverters(additionalJSONMediaTypes);
        builder = builder.messageConverters(converters);
        return builder.build();
    }

    /**
     * 生成HTTP消息转换器
     *
     * @return HTTP消息转换器列表
     */
    private static List<HttpMessageConverter<?>> buildMessageConverters(
            @Nullable MediaType[] additionalJSONMediaTypes) {
        FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter();
        appendMediaTypes(fastJsonHttpMessageConverter, additionalJSONMediaTypes);
        List<HttpMessageConverter<?>> converters = new ArrayList<>(1);
        converters.add(fastJsonHttpMessageConverter);
        return converters;
    }

    /**
     * 将其他媒体类型添加到消息转换器
     *
     * @param converter            消息转换器
     * @param additionalMediaTypes 媒体类型列表
     */
    private static void appendMediaTypes(@NotNull AbstractHttpMessageConverter<?> converter,
                                         @Nullable MediaType[] additionalMediaTypes) {
        if (additionalMediaTypes == null) {
            return;
        }
        List<MediaType> supportedMediaTypes = new ArrayList<>(converter.getSupportedMediaTypes());
        for (MediaType mediaType : additionalMediaTypes) {
            if (mediaType != null) {
                supportedMediaTypes.add(mediaType);
            }
        }
        converter.setSupportedMediaTypes(supportedMediaTypes);
    }

}
